package org.example.filter;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.config.LoginUser;
import org.example.domain.po.ErpUser;
import org.example.service.ErpMenuService;
import org.example.utils.JwtUtil;
import org.example.utils.RequestHolder;
import org.example.utils.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

// OncePerRequestFilter 是一个过滤器（Spring提供）
@Component
public class TokenFilter extends OncePerRequestFilter {
    private static List<String> whiteList = Arrays.asList(
            "/user/submitLogin", "/user/register", "/user/getUserCountByUserName", "/");

    @Value("${spring.profiles.active}")
    private String active;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private ErpMenuService erpMenuService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Map<String, String[]> parameterMap = request.getParameterMap();
        String method = request.getMethod();// 请求类型
        String requestURI = request.getRequestURI();
        if (method.equals("OPTIONS")){
            // 继续往下执行
            filterChain.doFilter(request, response);
            return;
        }
        // 获取用户IP地址
//        RequestHolder.set(ServletUtil.getClientIP(request));
        
        if (active.equals("dev")) { // 开发者模式
            ErpUser users = new ErpUser();
            users.setId(1L);
            users.setUsername("admin");
            users.setLoginName("admin");
            users.setTenantId(9L);
            LoginUser user = new LoginUser(users, erpMenuService.findMenusAdmin());
            UsernamePasswordAuthenticationToken authenticationToken
                    = new UsernamePasswordAuthenticationToken(
                    "admin",
                    null,
                    user.getAuthorities());
            request.setAttribute("user", user.getUsers());
            //将通知给security，我已经验证了token你就不需要验证了
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            //继续往下执行....
            filterChain.doFilter(request, response);
            return;
        }

        // 如果请求路径=白名单内容
        if (whiteList.contains(request.getRequestURI())){
            // 继续往下执行
            filterChain.doFilter(request, response);
            return;
        }
        
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setContentType("application/json;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        
        if (requestURI.equals("/quit")){
            String token = request.getHeader("token");
            Map<String, Object> strUser = JwtUtil.parseToken(token);
            request.removeAttribute("user");// 删除作用域的用户
            SecurityContextHolder.getContext().setAuthentication(null);
            redisTemplate.delete("login:" + strUser.get("username"));
            response.getWriter().write(new ObjectMapper().writeValueAsString(Result.success(200, "退出登录")));
            return;
        }

        String token = request.getHeader("token"); // 从请求的头部获取token
        ObjectMapper mapper = new ObjectMapper();
        // 验证是否有token
        if (StrUtil.hasEmpty(token)) {
            String json = mapper.writeValueAsString(Result.error(401, "你还未登录"));
            response.getWriter().write(json);
        } else {
            // 验证token是否已经过期
            if (JwtUtil.isExpired(token)){
                // 解析token获取信息
                Map<String, Object> strUserMapper = JwtUtil.parseToken(token);
                // 从redis中获取到用户信息和菜单信息（权限信息）
                LoginUser loginUser = (LoginUser) redisTemplate.opsForValue().get("login:" + strUserMapper.get("username"));
                if (loginUser == null) {
                    String json = mapper.writeValueAsString(Result.error(401, "已被强制下线，请重新登录"));
                    response.getWriter().write(json);
                } else {
                    UsernamePasswordAuthenticationToken authenticationToken
                            = new UsernamePasswordAuthenticationToken(
                            strUserMapper.get("username"),
                            null,
                            loginUser.getAuthorities());
                    // 存入request作用域
                    request.setAttribute("user", loginUser.getUsers());
                    // 将通知给security, 我已经验证了token你就不需要验证了
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                    // 上面验证都通过了，我就可以进去服务器
                    filterChain.doFilter(request, response);
                }
            } else {
                String json = mapper.writeValueAsString(Result.error(401, "登录已经过期，请重新登录"));
                response.getWriter().write(json);
            }
        }
    }
}
